home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / program / tjgold.zip / INSTALL.002 / GOLDIO2.PAS < prev    next >
Pascal/Delphi Source File  |  1995-07-12  |  62KB  |  2,131 lines

  1. {--------------------------------------------------------------------------}
  2. {                Product: TechnoJock's Turbo Toolkit                       }
  3. {                Version: GOLD                                             }
  4. {                Build:   1.01                                             }
  5. {                                                                          }
  6. {                Copyright 1986-1995  TechnoJock Software, Inc.            }
  7. {                           All Rights Reserved                            }
  8. {                          Restricted by License                           }
  9. {--------------------------------------------------------------------------}
  10.  
  11.                     {*********************************}
  12.                     {**       Unit:   GOLDIO2       **}
  13.                     {*********************************}
  14.  
  15. {+++++++++++++++++++++++++++++++} unit GOLDIO2; {++++++++++++++++++++++++++++}
  16.  
  17. {$I GOLDFLAG.INC}
  18. {$IFNDEF GOLDIO2}
  19.    {$DEFINE GOLDIO2}
  20. {$ENDIF}
  21.  
  22. {++++++++++++++++++++++++++++++++} INTERFACE {+++++++++++++++++++++++++++++++}
  23.  
  24. uses DOS, CRT, GoldHard, GoldTint, GoldMisc, GoldKey, GoldFast, GoldWin,
  25.      GoldLink, GoldStr, GoldDate, GoldIO, GoldList, GoldGrid;
  26.  
  27. type
  28.    StringChoice = string[3];
  29.  
  30.    IO2Set = record
  31.       ButtonWasDown:boolean;
  32.       CheckOff:stringchoice;
  33.       CheckOn:stringchoice;
  34.       RadioOff: stringchoice;
  35.       RadioOn: stringchoice;
  36.       ScrollLeft: char;
  37.       ScrollRight: char;
  38.       ButtonLeft: char;
  39.       ButtonRight: char;
  40. {$IFNDEF NOVGACHARS}
  41.       FancyCheckOff:stringchoice;
  42.       FancyCheckOn:stringchoice;
  43.       FancyRadioOff:stringchoice;
  44.       FancyRadioOn:stringchoice;
  45. {$ENDIF}
  46.    end; {IO2Set}
  47.  
  48.    GroupItemPtr = ^GroupItem;
  49.    GroupItem = record
  50.       NextPtr: GroupItemPtr;
  51.       StrPtr: ^string;
  52.       MsgPtr: ^string;
  53.       HK: word;
  54.       Selected: ^boolean;
  55.       X: byte;
  56.       Y: byte;
  57.       Active: boolean;
  58.    end;
  59.  
  60.    GroupInfoPtr = ^GroupInfo;
  61.    GroupInfo = record
  62.       TotalItems: byte;
  63.       ActiveItem: byte;
  64.       FirstItemPtr: GroupItemPtr;
  65.       RadioSource: ^byte;
  66.    end;
  67.  
  68. {button}
  69. procedure ButtonField(FieldID:integer; Face:string; Action:gAction);
  70. procedure ButtonDefaultField(FieldID:integer; Face:string; Action:gAction);
  71. procedure ButtonChangeSettings(FieldID:integer; Face:string; Action:gAction);
  72. procedure ButtonDisplay(FNP:FieldSettingsPtr;Status:gStatus);
  73. {common routine for check boxes and radio buttons}
  74. procedure CheckRadioSetActive(FieldID,ItemNum:integer;IsActive:boolean);
  75. {check boxes}
  76. procedure CheckField(FieldID:integer; width,depth:byte);
  77. procedure CheckAddItem(FieldID,ItemX,ItemY:integer; Str,Msg:string;ItemHK:word;var gResult:boolean);
  78. {radio buttons}
  79. procedure RadioField(FieldID:integer; width,depth:byte; var SelectedItem:byte);
  80. procedure RadioAddItem(FieldID,ItemX,ItemY:integer; Str,Msg:string;ItemHK:word);
  81. {list field}
  82. procedure ListField(FieldID:integer; width,depth:byte; var SelectedItem:integer);
  83. procedure ListAssignStrLL(FieldID:integer; var SL:StringLL);
  84. procedure ListUpdateStrLL(FieldID:integer; var SL:StringLL);
  85. function  ListLastKey(FieldID:integer):word;
  86. procedure ListAddItem(FieldID:integer; Str:string);
  87. procedure ListKwikAddItem(FieldID:integer; Str:string);
  88. procedure ListRebuild(FieldID:integer; Str:string);
  89. function  ListGetString(FieldID:integer; EntryNo:integer): string;
  90. function  ListGetActivePick(FieldID:integer): integer;
  91. {wrap or multi-column list field}
  92. procedure WrapListField(FieldID:integer;Colwidth,ColCount,RowCount:byte;var ListDetails: ListCfg);
  93. procedure GridListField(FieldID:integer;width,depth:byte;var ListDetails: ListCfg);
  94. {scroll field}
  95. procedure ScrollField(FieldID:integer; var Strvar:string;FieldL,MaxL:byte);
  96. procedure ScrollForceCase(FieldID:integer; FCase: gCase);
  97. {INTERNAL}
  98. procedure DoNothing(FSP:FieldSettingsPtr);
  99. function  SuspendOK:boolean;
  100. procedure ScrollDisplay(FSP:FieldSettingsPtr;Status:gStatus);
  101. function  ScrollKeyHandler(InKey:word;X,Y:byte):gAction;
  102. procedure DisposeScrollMemory(FNP:FieldSettingsPtr);
  103. procedure DisposeListMemory(FNP:FieldSettingsPtr);
  104. procedure SetFieldDefaults(FieldInfo: FieldSettingsPtr);
  105.  
  106. var
  107.    IO2Vars: IO2Set;
  108.  
  109. {+++++++++++++++++++++++++++++} IMPLEMENTATION {+++++++++++++++++++++++++++++}
  110.  
  111.                       {******************************}
  112.                       {**  Miscellaneous Routines  **}
  113.                       {******************************}
  114.  
  115. { Use IOSetError from GOLDIO }
  116.  
  117. {$IFOPT F-}
  118.    {$DEFINE FOFF}
  119.    {$F+}
  120. {$ENDIF}
  121. procedure DoNothing(FSP:FieldSettingsPtr);
  122. {}
  123. begin
  124. end; { DoNothing }
  125.  
  126. function SuspendOK:boolean;
  127. {}
  128. begin
  129.    SuspendOK := true;
  130. end; { Suspend }
  131. {$IFDEF FOFF}
  132.    {$F-}
  133.    {$UNDEF FOFF}
  134. {$ENDIF}
  135.  
  136. procedure SetFieldDefaults(FieldInfo: FieldSettingsPtr);
  137. {}
  138. begin
  139.    with FieldInfo^ do
  140.    begin
  141.       FieldType := IOOther;
  142.       DataPtr  := nil;
  143.       DataPtrS := nil;
  144.       DataSize := ButtonMarker;
  145.       RefreshFieldHook := DoNothing;
  146.       UpdateVarHook := DoNothing;
  147.       DisposeHook := BasicDisposeHook;
  148.    end;
  149. end; { SetFieldDefaults }
  150.  
  151.                      {*********************}
  152.                      {**  Button Fields  **}
  153.                      {*********************}
  154.  
  155. procedure WriteButton(Down: boolean);
  156. {}
  157. var BStr: StrButton;
  158. begin
  159.    with ActiveForm^ do
  160.       with ActiveFieldPtr^.FieldInfo^ do
  161.          if Down <> IO2Vars.ButtonWasDown then
  162.          with IOVars.Form[IOVars.CurrentForm]^ do
  163.          begin
  164.             BStr := IO2Vars.ButtonLeft+FieldStr+IO2Vars.ButtonRight;
  165.             if Down then
  166.             begin
  167.                DrawButtonDown(X1,X2,Y2,Col[IOButtonHiHot],
  168.                               Col[IOButtonHi],BStr);
  169.                gotoxy(succ(WhereX),WhereY);
  170.             end else
  171.             begin
  172.                DrawButton(X1,X2,Y2,Col[IOButtonHiHot],
  173.                           Col[IOButtonHi],BStr);
  174.                gotoxy(pred(WhereX),WhereY);
  175.             end;
  176.             IO2Vars.ButtonWasDown := Down;
  177.             if (ActiveForm^.WinNum <> 0) then
  178.                WinDrawTop;
  179.          end;
  180. end; { WriteButton }
  181.  
  182. function ButtonDown:boolean;
  183. {}
  184. var L,C,R: boolean;
  185.     X,Y:byte;
  186. begin
  187.    with ActiveForm^ do
  188.       with ActiveFieldPtr^.FieldInfo^ do
  189.       begin
  190.          IO2Vars.ButtonWasDown := false;
  191.          WriteButton(true);
  192.          repeat
  193.             MouseStatusWin(L,C,R,X,Y);
  194.             if L and ( (Y <> Y2) or (X < X1) or (X > X2+ord(IO2Vars.ButtonWasDown))) then
  195.                WriteButton(false)
  196.             else
  197.                WriteButton(true);
  198.          until not L;
  199.          ButtonDown := (X >= X1) and (X <= X2+ord(IO2Vars.ButtonWasDown)) and (Y = Y2);
  200.       end;
  201. end; { ButtonDown }
  202.  
  203. {$IFOPT F-}
  204.    {$DEFINE FOFF}
  205.    {$F+}
  206. {$ENDIF}
  207. procedure ButtonDisplay(FNP:FieldSettingsPtr;Status:gStatus);
  208. {}
  209. var A,B: byte;
  210. begin
  211.    case Status of
  212.       Activate,
  213.       HiStatus: with IOVars.Form[IOVars.CurrentForm]^ do begin
  214.          with FNP^ do begin
  215.             DrawButton(X1,X2,Y2,Col[IOButtonHiHot],
  216.                        Col[IOButtonHi],IO2Vars.ButtonLeft+FieldStr+IO2Vars.ButtonRight);
  217.             GotoXY(X1+(X2 - X1) div 2,Y2);
  218.          end;
  219.       end;
  220.       NormStatus,
  221.       OffStatus: with IOVars.Form[IOVars.CurrentForm]^ do
  222.       begin
  223.          if (Status= OffStatus) or (FNP^.Active <> FldOn) then
  224.          begin
  225.             A := Col[IOButtonOff];
  226.             B := Col[IOButtonOff];
  227.          end else
  228.          if FNP^.ID = DefaultButtonID then
  229.          begin
  230.             A := Col[IOButtonDefHot];
  231.             B := Col[IOButtonDef];
  232.          end else
  233.          begin
  234.             A := Col[IOButtonNormHot];
  235.             B := Col[IOButtonNorm];
  236.          end;
  237.          with FNP^ do
  238.                DrawButton(X1,X2,Y2,A,B,' '+FieldStr+' ')
  239.       end;
  240.    end; {case}
  241. end; { ButtonDisplay }
  242.  
  243. function ButtonKeyHandler(InKey:word;X,Y:byte):gAction;
  244. {}
  245. begin
  246.    ButtonKeyHandler := none;
  247.    with ActiveForm^ do
  248.       with ActiveFieldPtr^.FieldInfo^ do
  249.         case Inkey of
  250.            13: begin
  251.               ButtonKeyHandler := gAction(OMisc);
  252.               {animate the button press}
  253.                WriteButton(true);
  254.                delay(HardVars.AnimateDelay);
  255.                WriteButton(false)
  256.            end;
  257.            500: if (X >= X1) and (X <= X2) and (Y = Y1) and ButtonDown then
  258.            begin
  259.               ButtonKeyHandler := gAction(OMisc);
  260.               WriteButton(false);
  261.            end;
  262.         end; {case}
  263. end; { ButtonKeyHandler }
  264.  
  265. function ButtonHotKeyHandler(FNP:FieldSettingsPtr;var Key:word;var Act:gAction):boolean;
  266. {}
  267. var Selected: boolean;
  268. begin
  269.    if FNP <> nil then with FNP^ do
  270.       Selected := (Key <> 0) and (Key = HotKey) and (Active = FldOn)
  271.    else
  272.       Selected := false;
  273.    if Selected then
  274.    begin
  275.       Key := 0;
  276.       Act := gAction(FNP^.OMisc);
  277.    end;
  278.    ButtonHotKeyHandler := Selected;
  279. end; { ButtonHotKeyHandler }
  280.  
  281. {$IFDEF FOFF}
  282.    {$F-}
  283.    {$UNDEF FOFF}
  284. {$ENDIF}
  285.  
  286. procedure ButtonChangeSettings(FieldID:integer; Face:string; Action:gAction);
  287. {}
  288. var FNP: FieldNodePtr;
  289. begin
  290.    FNP := FieldPtr(FieldID);
  291.    if (FNP <> nil) then
  292.       with FNP^.FieldInfo^ do
  293.       begin
  294.          if FieldType = IOOther then
  295.          begin
  296.             OMisc := ord(Action);
  297.             FieldStr    := Face;
  298.             FieldLen    := length(strip('A',HiMarker,FieldStr));
  299.             X2          := X1 + succ(FieldLen);
  300.          end;
  301.       end;
  302. end; { ButtonChangeSettings }
  303.  
  304. procedure ButtonField(FieldID:integer; Face:string; Action:gAction);
  305. {}
  306. var FNP: FieldNodePtr;
  307. begin
  308.    FNP := FieldPtr(FieldID);
  309.    if (FNP <> nil) then
  310.       with FNP^.FieldInfo^ do
  311.       begin
  312.          SetFieldDefaults(FNP^.FieldInfo);
  313.          OMisc := ord(Action);
  314.          ProcesskeyHook := ButtonkeyHandler;
  315.          SuspendHook := SuspendOK;
  316.          DisplayHook := ButtonDisplay;
  317.          HotKeyHook := ButtonHotKeyHandler;
  318.          FieldStr    := Face;
  319.          FieldFmt    := '';
  320.          FieldLen    := length(strip('A',HiMarker,FieldStr));
  321.          X2          := X1 + succ(FieldLen);
  322.          UsesEnter := true;
  323.       end;
  324. end; { ButtonField }
  325.  
  326. procedure ButtonDefaultField(FieldID:integer; Face:string; Action:gAction);
  327. {}
  328. begin
  329.    ButtonField(FieldID,Face,Action);
  330.    ActiveForm^.DefaultButtonID := FieldID;
  331. end; { ButtonDefaultField }
  332.  
  333.  
  334.                       {*****************************}
  335.                       {**  Common Group Routines  **}
  336.                       {*****************************}
  337.  
  338. function GItemPtr(FSP:FieldSettingsPtr;ItemNum:byte): GroupItemPtr;
  339. {}
  340. var GIP: GroupItemPtr;
  341.     Counter: integer;
  342.     DP: GroupInfoPtr;
  343. begin
  344.    if (FSP <> nil) and (ItemNum > 0) then
  345.       with FSP^ do
  346.       begin
  347.          DP := DataPtr;
  348.          GIP := DP^.FirstItemPtr;
  349.          Counter := 1;
  350.          while (GIP <> nil) and (Counter < ItemNum) do
  351.          begin
  352.             GIP := GIP^.NextPtr;
  353.             inc(Counter);
  354.          end;
  355.          GItemPtr := GIP;
  356.       end
  357.    else
  358.       GItemPtr := nil;
  359. end; { GItemPtr }
  360.  
  361. function GroupItemID(X,Y:byte):byte;
  362. {}
  363. var IP: GroupInfoPtr;
  364.     GIP: GroupItemPtr;
  365.     Finished: boolean;
  366.     Counter: byte;
  367. begin
  368.    IP := ActiveForm^.ActiveFieldPtr^.FieldInfo^.DataPtr; {phew}
  369.    GIP := GItemPtr(ActiveForm^.ActiveFieldPtr^.FieldInfo,1);
  370.    Finished := false;
  371.    Counter := 1;
  372.    repeat
  373.       if  (GIP <> nil)
  374.       and (X >= ActiveForm^.ActiveFieldPtr^.FieldInfo^.X1 + pred(GIP^.X))
  375.       and (X <= ActiveForm^.ActiveFieldPtr^.FieldInfo^.X1 + GIP^.X + length(GIP^.StrPtr^) + 3)
  376.       and (Y = ActiveForm^.ActiveFieldPtr^.FieldInfo^.Y1 + pred(GIP^.Y))
  377.       and (GIP^.Active) then
  378.          Finished := true
  379.       else
  380.       if (GIP <> nil) then
  381.       begin
  382.         GIP := GIP^.NextPtr;
  383.         inc(Counter);
  384.       end;
  385.    until (Finished) or (GIP=nil);
  386.    if Finished then
  387.       GroupItemID := Counter
  388.    else
  389.       GroupItemID := 0;
  390. end; { GroupItemID }
  391.  
  392. procedure WriteGroupItem(FSP:FieldSettingsPtr;ItemNum:byte; Status:gStatus; Str:String);
  393. {}
  394. var GP:GroupItemPtr;
  395.     A,AHot: byte;
  396.     DP: GroupInfoPtr;
  397. begin
  398.    GP := GItemPtr(FSP,ItemNum);
  399.    if GP <> nil then
  400.       with GP^ do
  401.       begin
  402.          with IOVars.Form[IOVars.CurrentForm]^ do
  403.             if FSP^.Active <> FldOn then {whole field is off}
  404.             begin
  405.                A := Col[IOEditOff];
  406.                AHot := Col[IOEditOff];
  407.             end else
  408.             begin
  409.             case Status of
  410.                Activate,HiStatus: begin
  411.                   DP := FSP^.DataPtr;
  412.                   if ItemNum = DP^.ActiveItem then
  413.                   begin
  414.                      A := Col[IOChoiceHi];
  415.                      AHot:= Col[IOChoiceHiHot];
  416.                      GotoXY(FSP^.X1+GP^.X+1,pred(FSP^.Y1)+GP^.Y);
  417.                   end else
  418.                   begin
  419.                      A := Col[IOChoiceNorm];
  420.                      AHot := Col[IOChoiceNormHot];
  421.                   end;
  422.                   RemoveMessage(FSP);
  423.                   if MsgPtr <> nil then
  424.                      DisplayMessage(FSP,MsgPtr^);
  425.                end;
  426.                NormStatus: begin
  427.                   if Active then
  428.                   begin
  429.                      A := Col[IOChoiceNorm];
  430.                      AHot := Col[IOChoiceNormHot];
  431.                   end else
  432.                   begin
  433.                      A := Col[IOChoiceOff];
  434.                      AHot := Col[IOChoiceOff];
  435.                   end;
  436.                end;
  437.                OffStatus: begin
  438.                   A := Col[IOChoiceOff];
  439.                   AHot := Col[IOChoiceOff];
  440.                end;
  441.             end;
  442.          end;
  443.          with FSP^ do
  444.            WriteHi(pred(X1)+GP^.X,pred(Y1)+GP^.Y,
  445.                     AHot,A,Str);
  446.       end;
  447. end; { WriteGroupItem }
  448.  
  449. procedure GroupAddItem(FieldID,ItemX,ItemY:integer; Str,Msg:string;ItemHK:word);
  450. {}
  451. var FNP: FieldNodePtr;
  452.     GrpPtr: GroupItemPtr;
  453.     GrpInfoPtr: GroupInfoPtr;
  454. begin
  455.    FNP := FieldPtr(FieldID);
  456.    if (FNP <> nil) then
  457.       with FNP^.FieldInfo^ do
  458.       begin
  459.          if GoldMaxAvail < +sizeof(GroupInfo) + sizeof(GroupItem) + succ(length(Str)) then
  460.             IOSetError(1008);
  461.          if (DataPtr = nil) then
  462.          begin
  463.             DataSize := -1;
  464.             getmem(DataPtr,sizeof(GroupInfo));
  465.             GrpInfoPtr := DataPtr;
  466.             GrpInfoPtr^.TotalItems := 0;
  467.             GrpInfoPtr^.ActiveItem := 0;
  468.             getmem(GrpInfoPtr^.FirstItemPtr,sizeof(GrpInfoPtr^.FirstItemPtr^));
  469.             GrpPtr := GrpInfoPtr^.FirstItemPtr;
  470.          end else
  471.          begin
  472.             GrpInfoPtr := DataPtr;
  473.             GrpPtr := GrpInfoPtr^.FirstItemPtr;
  474.             while GrpPtr^.NextPtr <> nil do
  475.                GrpPtr := GrpPtr^.NextPtr;
  476.             getmem(GrpPtr^.NextPtr,sizeof(groupItem));
  477.             GrpPtr := GrpPtr^.NextPtr;
  478.          end;
  479.          with GrpPtr^ do
  480.          begin
  481.             NextPtr := nil;
  482.             if Str = '' then
  483.                StrPtr := nil
  484.             else
  485.             begin
  486.                getmem(StrPtr,succ(length(Str)));
  487.                move(Str[0],StrPtr^,succ(length(Str)));
  488.             end;
  489.             if Msg = '' then
  490.                MsgPtr := nil
  491.             else
  492.             begin
  493.                getmem(MsgPtr,succ(length(Msg)));
  494.                move(Msg[0],MsgPtr^,succ(length(Msg)));
  495.             end;
  496.             HK := ItemHK;
  497.             X := ItemX;
  498.             Y := ItemY;
  499.             Active := true;
  500.             with GrpInfoPtr^ do
  501.             begin
  502.                inc(TotalItems);
  503.                if ActiveItem = 0 then
  504.                   ActiveItem := TotalItems;
  505.             end;
  506.          end;
  507.       end;
  508. end; { GroupAddItem }
  509.  
  510. {$IFOPT F-}
  511.    {$DEFINE FOFF}
  512.    {$F+}
  513. {$ENDIF}
  514. procedure DisposeGroupMemory(FNP:FieldSettingsPtr);
  515. {Disposes of heap memory allocated by group add item}
  516. var GrpPtr1,GrpPtr2: GroupItemPtr;
  517.     GrpInfoPtr: GroupInfoPtr;
  518. begin
  519.    if (FNP^.DataPtr <> nil) then
  520.    begin
  521.       GrpPtr2 := GroupInfoPtr(FNP^.DataPtr)^.FirstItemPtr;
  522.       while GrpPtr2 <> nil do
  523.       begin
  524.          GrpPtr1 := GrpPtr2;
  525.          GrpPtr2 := GrpPtr1^.NextPtr;
  526.          if GrpPtr1^.StrPtr <> nil then
  527.             freemem(GrpPtr1^.StrPtr,byte(succ(GrpPtr1^.StrPtr^[0])));
  528.          if GrpPtr1^.MsgPtr <> nil then
  529.             freemem(GrpPtr1^.MsgPtr,byte(succ(GrpPtr1^.MsgPtr^[0])));
  530.          freemem(GrpPtr1,sizeof(GrpPtr1^));
  531.       end;
  532.       freemem(FNP^.DataPtr,sizeof(GroupInfo));
  533.    end;
  534. end; { DisposeGroupMemory }
  535. {$IFDEF FOFF}
  536.    {$F-}
  537.    {$UNDEF FOFF}
  538. {$ENDIF}
  539.  
  540. function GroupHotKeyEngine(FNP:FieldSettingsPtr;var Key:word):byte;
  541. {}
  542. var GIP: GroupItemPtr;
  543.     Selected:boolean;
  544.     ItemID: byte;
  545. begin
  546.    Selected := false;
  547.    ItemID := 0;
  548.    if (FNP <> nil) and (Key <> 0) and (FNP^.Active = FldOn) then with FNP^ do
  549.    begin
  550.       GIP := GroupInfoPtr(DataPtr)^.FirstItemPtr;
  551.       while (GIP <> nil) and not Selected do
  552.       begin
  553.          inc(ItemID);
  554.          Selected := (GIP^.HK = Key) and (GIP^.Active);
  555.          if not Selected then
  556.             GIP := GIP^.NextPtr;
  557.       end;
  558.    end;
  559.    if GIP = nil then
  560.       GroupHotKeyEngine := 0
  561.    else
  562.       GroupHotKeyEngine := ItemID;
  563. end; { GroupHotKeyEngine }
  564.  
  565.                       {***********************}
  566.                       {**  Check Box Field  **}
  567.                       {***********************}
  568.  
  569. procedure WriteCheckItem(FSP:FieldSettingsPtr;ItemNum:byte; Status:gStatus);
  570. {}
  571. var GP:GroupItemPtr;
  572.     Str: StrScreen;
  573.     SC: stringchoice;
  574. begin
  575.    GP := GItemPtr(FSP,ItemNum);
  576.    if GP <> nil then
  577.       with GP^ do
  578.       begin
  579. {$IFNDEF NOVGACHARS}
  580.          if FastVars.CustomCharsActive then
  581.          begin
  582.             if Selected^ then
  583.                SC := IO2Vars.FancyCheckOn
  584.             else
  585.                SC := IO2Vars.FancyCheckOff;
  586.          end else
  587.          begin
  588.             if Selected^ then
  589.                SC := IO2Vars.CheckOn
  590.             else
  591.                SC := IO2Vars.CheckOff;
  592.          end;
  593. {$ELSE}
  594.          if Selected^ then
  595.             SC := CheckOn
  596.          else
  597.             SC := CheckOff;
  598. {$ENDIF}
  599.          WriteGroupItem(FSP,ItemNum,Status,' '+SC+' '+StrPtr^);
  600.      end;
  601. end; { WriteCheckItem }
  602.  
  603. procedure WriteAllCheckItems(FSP:FieldSettingsPtr;Status:gStatus);
  604. {}
  605. var I: integer;
  606.     GIP: GroupInfoPtr;
  607. begin
  608.    GIP := FSP^.DataPtr;
  609.    for I := 1 to GIP^.TotalItems do
  610.        WriteCheckItem(FSP,I,Status);
  611. end; { WriteAllCheckItems }
  612.  
  613. procedure CheckChangeActiveState(FSP:FieldSettingsPtr);
  614. {}
  615. var IP: GroupInfoPtr;
  616.     GIP: GroupItemPtr;
  617. begin
  618.    IP := FSP^.DataPtr;
  619.    GIP := GItemPtr(FSP,IP^.ActiveItem);
  620.    GIP^.Selected^ := not GIP^.Selected^;
  621.    WriteCheckItem(FSP,IP^.ActiveItem,HiStatus);
  622. end; { CheckChangeActiveState }
  623.  
  624. procedure CheckScrollDown;
  625. {}
  626. var IP: GroupInfoPtr;
  627.     GIP: GroupItemPtr;
  628. begin
  629.    with ActiveForm^.ActiveFieldPtr^ do
  630.    begin
  631.       IP := FieldInfo^.DataPtr;
  632.       if IP^.ActiveItem <> 0 then
  633.       begin
  634.          GIP := GItemPtr(FieldInfo,IP^.ActiveItem);
  635.          WriteCheckItem(FieldInfo,IP^.ActiveItem,NormStatus);
  636.          repeat
  637.             if IP^.ActiveItem < IP^.TotalItems then
  638.                inc(IP^.ActiveItem)
  639.             else
  640.                IP^.ActiveItem := 1;
  641.             GIP := GItemPtr(FieldInfo,IP^.ActiveItem);
  642.          until GIP^.Active = true;
  643.          WriteCheckItem(FieldInfo,IP^.ActiveItem,NormStatus);
  644.       end;
  645.    end;
  646. end; { CheckScrollDown }
  647.  
  648. procedure CheckScrollUp;
  649. {}
  650. var IP: GroupInfoPtr;
  651.     GIP: GroupItemPtr;
  652. begin
  653.    with ActiveForm^.ActiveFieldPtr^ do
  654.    begin
  655.       IP := FieldInfo^.DataPtr;
  656.       if IP^.ActiveItem <> 0 then
  657.       begin
  658.          GIP := GItemPtr(FieldInfo,IP^.ActiveItem);
  659.          WriteCheckItem(FieldInfo,IP^.ActiveItem,NormStatus);
  660.          repeat
  661.             if IP^.ActiveItem > 1 then
  662.                dec(IP^.ActiveItem)
  663.             else
  664.                IP^.ActiveItem := IP^.TotalItems;
  665.             GIP := GItemPtr(FieldInfo,IP^.ActiveItem);
  666.          until GIP^.Active = true;
  667.          WriteCheckItem(FieldInfo,IP^.ActiveItem,NormStatus);
  668.       end;
  669.    end;
  670. end; { CheckScrollUp }
  671.  
  672. procedure CheckMouseDown(X,Y:byte);
  673. {Called when the mouse button is pressed down}
  674. var TargetField: byte;
  675.     IP: GroupInfoPtr;
  676.     L,M,R: boolean;
  677.     XM,YM: byte;
  678.     CursorVisible: boolean;
  679. begin
  680.    TargetField := GroupItemID(X,Y);
  681.    if TargetField <> 0 then
  682.    begin
  683.       IP := ActiveForm^.ActiveFieldPtr^.FieldInfo^.DataPtr;
  684.       if IP^.ActiveItem <> TargetField then
  685.       begin
  686.          WriteCheckItem(ActiveForm^.ActiveFieldPtr^.FieldInfo,IP^.ActiveItem,NormStatus);
  687.          IP^.ActiveItem := TargetField;
  688.          WriteCheckItem(ActiveForm^.ActiveFieldPtr^.FieldInfo,IP^.ActiveItem,HiStatus);
  689.       end;
  690.       CursorVisible := true;
  691.       repeat
  692.          MouseStatusWin(L,M,R,XM,YM);
  693.          if GroupItemID(XM,YM) = TargetField then
  694.          begin
  695.             if not CursorVisible then
  696.             begin
  697.                CursorOn;
  698.                CursorVisible := true;
  699.             end;
  700.          end else
  701.          begin
  702.            if CursorVisible then
  703.            begin
  704.               CursorOff;
  705.               CursorVisible := false;
  706.            end;
  707.          end;
  708.       until not L;
  709.       CursorOn;
  710.       MouseRelease; {clear the mouse buffers}
  711.       if GroupItemID(XM,YM) = TargetField then
  712.          CheckChangeActiveState(ActiveForm^.ActiveFieldPtr^.FieldInfo);
  713.    end else
  714.       MouseRelease;
  715. end; { CheckMouseDown }
  716.  
  717. procedure CheckFocusOnActive;
  718. {Makes sure that the item with focus is actually active, i.e. enabled}
  719. var IP: GroupInfoPtr;
  720.     GIP: GroupItemPtr;
  721.     FocusID: integer;
  722. begin
  723.    with ActiveForm^.ActiveFieldPtr^ do
  724.    begin
  725.       IP := FieldInfo^.DataPtr;
  726.       if IP^.ActiveItem <> 0 then
  727.       begin
  728.          GIP := GItemPtr(FieldInfo,IP^.ActiveItem);
  729.          FocusID := IP^.ActiveItem;
  730.          if GIP^.Active = false then
  731.          begin
  732.             repeat
  733.                if IP^.ActiveItem < IP^.TotalItems then
  734.                   inc(IP^.ActiveItem)
  735.                else
  736.                   IP^.ActiveItem := 1;
  737.                GIP := GItemPtr(FieldInfo,IP^.ActiveItem);
  738.             until (GIP^.Active) or (FocusID = IP^.ActiveItem);
  739.             if not GIP^.Active then
  740.                IP^.ActiveItem := 0;
  741.          end;
  742.       end;
  743.    end;
  744. end; { CheckFocusOnActive }
  745.  
  746. {$IFOPT F-}
  747.    {$DEFINE FOFF}
  748.    {$F+}
  749. {$ENDIF}
  750. procedure CheckDisplay(FSP:FieldSettingsPtr;Status:gStatus);
  751. {}
  752. var GIP: GroupInfoPtr;
  753. begin
  754.    with IOVars.Form[IOVars.CurrentForm]^ do
  755.    case Status of
  756.       Activate,
  757.       HiStatus: begin
  758.          CheckFocusOnActive;
  759.          with FSP^ do begin
  760.              GIP := DataPtr;
  761.              WriteCheckItem(FSP,GIP^.ActiveItem,HiStatus);
  762.              CursorOn;
  763.          end;
  764.       end;
  765.       OffStatus,
  766.       NormStatus: begin
  767.          with FSP^ do
  768.          begin
  769.             if Active = FldOn then
  770.                PartClear(X1,Y1,X2,Y2,Col[IOChoiceNorm],' ')
  771.             else
  772.                PartClear(X1,Y1,X2,Y2,Col[IOEditOff],' ');
  773.             WriteAllCheckItems(FSP,Status);
  774.          end;
  775.       end;
  776.    end; {case}
  777. end; { CheckDisplay }
  778.  
  779. function CheckKeyHandler(InKey:word;X,Y:byte):gAction;
  780. {}
  781. begin
  782.    CheckKeyHandler := none;
  783.    with ActiveForm^ do
  784.       with ActiveFieldPtr^.FieldInfo^ do
  785.         case Inkey of
  786.            32: begin
  787.                   CheckChangeActiveState(ActiveFieldPtr^.FieldInfo);
  788.                end;
  789.           500: begin
  790.                   CheckMouseDown(X,Y);
  791.                end;
  792.       328,331: begin
  793.                   CheckScrollUp;
  794.                end;
  795.       333,336: begin
  796.                   CheckScrollDown;
  797.                end;
  798.         end; {case}
  799. end; { CheckKeyHandler }
  800.  
  801. function CheckHotkeyHandler(FSP:FieldSettingsPtr;var Key:word;var Act:gAction): boolean;
  802. {}
  803. var ItemID: byte;
  804.     IP: GroupInfoPtr;
  805. begin
  806.    with FSP^ do
  807.    begin
  808.       if (Key <> 0) and (Key = HotKey) and (Active = FldOn)
  809.       and (IOVars.Form[IOVars.CurrentForm]^.ActiveFieldPtr^.FieldInfo <> FSP) then
  810.       begin
  811.          Key := 0;  {absorb the key}
  812.          CheckHotkeyHandler := true;
  813.       end
  814.       else
  815.       begin
  816.          ItemID := GroupHotkeyEngine(FSP,Key);
  817.          if ItemID <> 0 then   {choice hotkey pressed}
  818.          begin
  819.             IP :=  FSP^.DataPtr;
  820.             WriteCheckItem(FSP,IP^.ActiveItem,NormStatus);
  821.             IP^.ActiveItem := ItemID;
  822.             CheckChangeActiveState(FSP);
  823.             CheckHotkeyHandler := true;
  824.          end else
  825.             CheckHotkeyHandler := false;
  826.       end;
  827.    end;
  828. end; { CheckHotkeyHandler }
  829.  
  830. {$IFDEF FOFF}
  831.    {$F-}
  832.    {$UNDEF FOFF}
  833. {$ENDIF}
  834.  
  835. procedure CheckField(FieldID:integer; width,depth:byte);
  836. {}
  837. var FNP: FieldNodePtr;
  838. begin
  839.    FNP := FieldPtr(FieldID);
  840.    if (FNP <> nil) then
  841.       with FNP^.FieldInfo^ do
  842.       begin
  843.          SetFieldDefaults(FNP^.FieldInfo);
  844.          X2 := X1 + pred(width);
  845.          Y2 := Y1 + pred(depth);
  846.          ProcesskeyHook := CheckKeyHandler;
  847.          SuspendHook := SuspendOK;
  848.          DisplayHook := CheckDisplay;
  849.          HotKeyHook := CheckHotKeyHandler;
  850.          DisposeHook := DisposeGroupMemory;
  851.          FieldStr    := '';
  852.          FieldFmt    := '';
  853.          FieldLen    := 0;
  854.          OMisc       := CheckFld;
  855.          UsesCursors := true;
  856.       end;
  857. end; { CheckField }
  858.  
  859. procedure CheckAddItem(FieldID,ItemX,ItemY:integer; Str,Msg:string;ItemHK:word;var gResult:boolean);
  860. {}
  861. var FNP: FieldNodePtr;
  862.     GrpPtr: GroupItemPtr;
  863.     GrpInfoPtr: GroupInfoPtr;
  864. begin
  865.    FNP := FieldPtr(FieldID);
  866.    if (FNP <> nil) then
  867.       with FNP^.FieldInfo^ do
  868.       begin
  869.          if OMisc <> CheckFld then
  870.             IOSetError(1007);
  871.          GroupAddItem(FieldID,ItemX,ItemY,Str,Msg,ItemHK);
  872.          GrpInfoPtr := FNP^.FieldInfo^.DataPtr;
  873.          GRPPtr := GItemPtr(FNP^.FieldInfo,GrpInfoPtr^.TotalItems);
  874.          GrpPtr^.Selected := @gResult;
  875.       end;
  876. end; { CheckAddItem }
  877.  
  878. procedure CheckRadioSetActive(FieldID,ItemNum:integer;IsActive:boolean);
  879. {}
  880. var FNP: FieldNodePtr;
  881.     GIP: GroupItemPtr;
  882.     IP: GroupInfoPtr;
  883. begin
  884.    FNP := FieldPtr(FieldID);
  885.    if (FNP <> nil) then
  886.       with FNP^.FieldInfo^ do
  887.          if OMisc in [CheckFld,RadioFld] then
  888.          begin
  889.             IP := FNP^.FieldInfo^.DataPtr;
  890.             GIP := GItemPtr(FNP^.FieldInfo,ItemNum);
  891.             if GIP <> nil then
  892.                GIP^.Active := IsActive;
  893.          end;
  894. end; { CheckRadioSetActive }
  895.  
  896.                      {*********************}
  897.                      {**  RADIO BUTTONS  **}
  898.                      {*********************}
  899.  
  900. procedure WriteRadioItem(FSP:FieldSettingsPtr;ItemNum:byte; Status:gStatus);
  901. {}
  902. var GP:GroupItemPtr;
  903.     Str: StrScreen;
  904.     SC: stringchoice;
  905. begin
  906.    GP := GItemPtr(FSP,ItemNum);
  907.    if GP <> nil then
  908.       with GP^ do
  909.       begin
  910. {$IFNDEF NOVGACHARS}
  911.          if FastVars.CustomCharsActive then
  912.          begin
  913.             if byte(FSP^.SourcePtr^) = ItemNum then
  914.                SC := IO2Vars.FancyRadioOn
  915.             else
  916.                SC := IO2Vars.FancyRadioOff;
  917.          end else
  918.          begin
  919.             if byte(FSP^.SourcePtr^) = ItemNum then
  920.                SC := IO2Vars.RadioOn
  921.             else
  922.                SC := IO2Vars.RadioOff;
  923.          end;
  924. {$ELSE}
  925.          if byte(FSP^.SourcePtr^) = ItemNum then
  926.             SC := RadioOn
  927.          else
  928.             SC := RadioOff;
  929. {$ENDIF}
  930.          WriteGroupItem(FSP,ItemNum,Status,' '+SC+' '+StrPtr^);
  931.       end;
  932. end; { WriteRadioItem }
  933.  
  934. procedure WriteAllRadioItems(FSP:FieldSettingsPtr;Status:gStatus);
  935. {}
  936. var I: integer;
  937.     GIP: GroupInfoPtr;
  938. begin
  939.    GIP := FSP^.DataPtr;
  940.    for I := 1 to GIP^.TotalItems do
  941.        WriteRadioItem(FSP,I,Status);
  942. end; { WriteAllRadioItems }
  943.  
  944. procedure RadioChangeSelectedOption(FSP:FieldSettingsPtr; NewSelection:byte);
  945. {}
  946. var
  947.    OwnerByte: ^byte;
  948.    GIP: GroupInfoPtr;
  949.    ClearAll:boolean;
  950. begin
  951.    with FSP^ do
  952.    begin
  953.       GIP := DataPtr;
  954.       OwnerByte := SourcePtr;
  955.       ClearAll := OwnerByte^ <> GIP^.ActiveItem;
  956.       OwnerByte^ := NewSelection;
  957.       if ClearAll then
  958.          WriteAllRadioItems(FSP,NormStatus)
  959.       else
  960.          WriteRadioItem(FSP,GIP^.ActiveItem,NormStatus);
  961.       GIP^.ActiveItem := NewSelection;
  962.       WriteRadioItem(FSP,NewSelection,NormStatus);
  963.    end;
  964. end; { RadioChangeSelectedOption }
  965.  
  966. procedure RadioScrollDown;
  967. {}
  968. var IP: GroupInfoPtr;
  969.     GIP: GroupItemPtr;
  970.     NewSelection: byte;
  971. begin
  972.    with ActiveForm^.ActiveFieldPtr^ do
  973.    begin
  974.       IP := FieldInfo^.DataPtr;
  975.       if IP^.ActiveItem <> 0 then
  976.       begin
  977.          GIP := GItemPtr(FieldInfo,IP^.ActiveItem);
  978.          NewSelection := IP^.ActiveItem;
  979.          repeat
  980.             if NewSelection < IP^.TotalItems then
  981.                inc(NewSelection)
  982.             else
  983.                NewSelection := 1;
  984.             GIP := GItemPtr(FieldInfo,NewSelection);
  985.          until GIP^.Active = true;
  986.          RadioChangeSelectedOption(ActiveForm^.ActiveFieldPtr^.FieldInfo,NewSelection);
  987.       end;
  988.    end;
  989. end; { RadioScrollDown }
  990.  
  991. procedure RadioScrollUp;
  992. {}
  993. var IP: GroupInfoPtr;
  994.     GIP: GroupItemPtr;
  995.     NewSelection : byte;
  996. begin
  997.    with ActiveForm^.ActiveFieldPtr^ do
  998.    begin
  999.       IP := FieldInfo^.DataPtr;
  1000.       if IP^.ActiveItem <> 0 then
  1001.       begin
  1002.          GIP := GItemPtr(FieldInfo,IP^.ActiveItem);
  1003.          NewSelection := IP^.ActiveItem;
  1004.          repeat
  1005.             if NewSelection > 1 then
  1006.                dec(NewSelection)
  1007.             else
  1008.                NewSelection := IP^.TotalItems;
  1009.             GIP := GItemPtr(FieldInfo,NewSelection);
  1010.          until GIP^.Active = true;
  1011.          RadioChangeSelectedOption(ActiveForm^.ActiveFieldPtr^.FieldInfo,NewSelection);
  1012.       end;
  1013.    end;
  1014. end; { RadioScrollUp }
  1015.  
  1016. procedure RadioSelectActiveItem(FSP:FieldSettingsPtr);
  1017. {}
  1018. var OwnerByte: ^byte;
  1019.     GIP: GroupInfoPtr;
  1020. begin
  1021.    with FSP^ do
  1022.    begin
  1023.       GIP := DataPtr;
  1024.       OwnerByte := SourcePtr;
  1025.       if OwnerByte^ <> GIP^.ActiveItem then
  1026.          RadioChangeSelectedOption(FSP,GIP^.ActiveItem);
  1027.    end;
  1028. end; { RadioSelectActiveItem }
  1029.  
  1030. procedure RadioCheckActiveIsSelected(FSP:FieldSettingsPtr);
  1031. {Called when field is activated to ensure that the selected item is the
  1032.  active item}
  1033. var OwnerByte: ^byte;
  1034.     GIP: GroupInfoPtr;
  1035. begin
  1036.    with FSP^ do
  1037.    begin
  1038.       GIP := DataPtr;
  1039.       OwnerByte := SourcePtr;
  1040.       if OwnerByte^ <> GIP^.ActiveItem then
  1041.       begin
  1042.          GIP^.ActiveItem := OwnerByte^;
  1043.          WriteAllRadioItems(FSP,HiStatus);
  1044.       end;
  1045.    end;
  1046. end; { RadioCheckActiveIsSelected }
  1047.  
  1048. procedure RadioMouseDown(X,Y:byte);
  1049. {Called when the mouse button is pressed down}
  1050. var TargetField: byte;
  1051.     IP: GroupInfoPtr;
  1052.     L,M,R: boolean;
  1053.     XM,YM: byte;
  1054.     CursorVisible: boolean;
  1055. begin
  1056.    TargetField := GroupItemID(X,Y);
  1057.    if TargetField <> 0 then
  1058.    begin
  1059.       IP := ActiveForm^.ActiveFieldPtr^.FieldInfo^.DataPtr;
  1060.       if IP^.ActiveItem <> TargetField then
  1061.       begin
  1062.          WriteRadioItem(ActiveForm^.ActiveFieldPtr^.FieldInfo,IP^.ActiveItem,NormStatus);
  1063.          IP^.ActiveItem := TargetField;
  1064.          WriteRadioItem(ActiveForm^.ActiveFieldPtr^.FieldInfo,IP^.ActiveItem,HiStatus);
  1065.       end;
  1066.       CursorVisible := true;
  1067.       repeat
  1068.          MouseStatusWin(L,M,R,XM,YM);
  1069.          if GroupItemID(XM,YM) = TargetField then
  1070.          begin
  1071.             if not CursorVisible then
  1072.             begin
  1073.                CursorOn;
  1074.                CursorVisible := true;
  1075.             end;
  1076.          end else
  1077.          begin
  1078.            if CursorVisible then
  1079.            begin
  1080.               CursorOff;
  1081.               CursorVisible := false;
  1082.            end;
  1083.          end;
  1084.       until not L;
  1085.       CursorOn;
  1086.       MouseRelease; {clease the mouse buffers}
  1087.       if GroupItemID(XM,YM) = TargetField then
  1088.          RadioChangeSelectedOption(ActiveForm^.ActiveFieldPtr^.FieldInfo,TargetField);
  1089.    end else
  1090.       MouseRelease;
  1091. end; { RadioMouseDown }
  1092.  
  1093. {$IFOPT F-}
  1094.    {$DEFINE FOFF}
  1095.    {$F+}
  1096. {$ENDIF}
  1097. procedure RadioDisplay(FSP:FieldSettingsPtr;Status:gStatus);
  1098. {}
  1099. var GIP: GroupInfoPtr;
  1100. begin
  1101.    with IOVars.Form[IOVars.CurrentForm]^ do
  1102.    case Status of
  1103.       Activate,
  1104.       HiStatus: begin
  1105.          with FSP^ do begin
  1106.              if Status = Activate then
  1107.                 RadioCheckActiveIsSelected(FSP);
  1108.              CheckFocusOnActive;
  1109.              GIP := DataPtr;
  1110.              WriteRadioItem(FSP,GIP^.ActiveItem,HiStatus);
  1111.              CursorOn;
  1112.          end;
  1113.       end;
  1114.       OffStatus,
  1115.       NormStatus: begin
  1116.          with FSP^ do
  1117.          begin
  1118.             if Active = FldOn then
  1119.                PartClear(X1,Y1,X2,Y2,Col[IOChoiceNorm],' ')
  1120.             else
  1121.                PartClear(X1,Y1,X2,Y2,Col[IOEditOff],' ');
  1122.             WriteAllRadioItems(FSP,Status);
  1123.          end;
  1124.       end;
  1125.    end; {case}
  1126. end; { RadioDisplay }
  1127.  
  1128. function RadioHotkeyHandler(FSP:FieldSettingsPtr;var Key:word;var Act:gAction): boolean;
  1129. {}
  1130. var ItemID: byte;
  1131.     IP: GroupInfoPtr;
  1132. begin
  1133.    with FSP^ do
  1134.    begin
  1135.       if (Key <> 0) and (Key = HotKey) and (Active = FldOn)
  1136.       and (IOVars.Form[IOVars.CurrentForm]^.ActiveFieldPtr^.FieldInfo <> FSP) then
  1137.       begin
  1138.          Key := 0;  {absorb the key}
  1139.          RadioHotkeyHandler := true;
  1140.       end
  1141.       else
  1142.       begin
  1143.          ItemID := GroupHotkeyEngine(FSP,Key);
  1144.          if ItemID <> 0 then   {choice hotkey pressed}
  1145.          begin
  1146.             IP :=  FSP^.DataPtr;
  1147.             if IP^.ActiveItem <> ItemID then
  1148.             begin
  1149.                IP^.ActiveItem := ItemID;
  1150.                RadioSelectActiveItem(FSP);
  1151.             end;
  1152.             RadioHotkeyHandler := true;
  1153.          end else
  1154.             RadioHotkeyHandler := false;
  1155.       end;
  1156.    end;
  1157. end; { RadioHotkeyHandler }
  1158.  
  1159. function RadioKeyHandler(InKey:word;X,Y:byte):gAction;
  1160. {}
  1161. var Dummy: gAction;
  1162. begin
  1163.    RadioKeyHandler := none;
  1164.    with ActiveForm^ do
  1165.       with ActiveFieldPtr^.FieldInfo^ do
  1166.         case Inkey of
  1167.            32: begin
  1168.               RadioSelectActiveItem(ActiveForm^.ActiveFieldPtr^.FieldInfo);
  1169.            end;
  1170.            500: begin
  1171.               RadioMouseDown(X,Y);
  1172.            end;
  1173.            328,331: begin
  1174.               RadioScrollUp;
  1175.            end;
  1176.            333,336: begin
  1177.               RadioScrollDown;
  1178.            end;
  1179.         end; {case}
  1180. end; { RadioKeyHandler }
  1181.  
  1182. {$IFDEF FOFF}
  1183.    {$F-}
  1184.    {$UNDEF FOFF}
  1185. {$ENDIF}
  1186.  
  1187. procedure RadioField(FieldID:integer; width,depth:byte; var SelectedItem:byte);
  1188. {}
  1189. var FNP: FieldNodePtr;
  1190. begin
  1191.    FNP := FieldPtr(FieldID);
  1192.    if (FNP <> nil) then
  1193.       with FNP^.FieldInfo^ do
  1194.       begin
  1195.          SetFieldDefaults(FNP^.FieldInfo);
  1196.          X2 := X1 + pred(width);
  1197.          Y2 := Y1 + pred(depth);
  1198.          ProcesskeyHook := RadioKeyHandler;
  1199.          SuspendHook := SuspendOK;
  1200.          DisplayHook := RadioDisplay;
  1201.          HotKeyHook := RadioHotKeyHandler;
  1202.          DisposeHook := DisposeGroupMemory;
  1203.          FieldStr    := '';
  1204.          FieldFmt    := '';
  1205.          FieldLen    := 0;
  1206.          OMisc       := RadioFld;
  1207.          UsesCursors := true;
  1208.          SourcePtr := @SelectedItem;
  1209.       end;
  1210. end; { RadioField }
  1211.  
  1212. procedure RadioAddItem(FieldID,ItemX,ItemY:integer; Str,Msg:string;ItemHK:word);
  1213. {}
  1214. var FNP: FieldNodePtr;
  1215. begin
  1216.    FNP := FieldPtr(FieldID);
  1217.    if (FNP <> nil) then
  1218.       with FNP^.FieldInfo^ do
  1219.       begin
  1220.          if OMisc <> RadioFld then
  1221.             IOSetError(1007);
  1222.          GroupAddItem(FieldID,ItemX,ItemY,Str,Msg,ItemHK);
  1223.       end;
  1224. end; { RadioAddItem }
  1225.  
  1226.                      {*****************************}
  1227.                      {**  Common List Functions  **}
  1228.                      {*****************************}
  1229.  
  1230. {$IFOPT F-}
  1231.    {$DEFINE FOFF}
  1232.    {$F+}
  1233. {$ENDIF}
  1234. procedure DisposeListMemory(FNP:FieldSettingsPtr);
  1235. {Disposes of heap memory allocated by group add item}
  1236. begin
  1237.    if (FNP^.DataPtr <> nil) then
  1238.    begin
  1239.       if ListCfg(FNP^.DataPtr^).IODispose then
  1240.       begin
  1241.          StrLLDestroy(StringLLPtr(ListCfg(FNP^.DataPtr^).DataSource)^);
  1242.          freemem(ListCfg(FNP^.DataPtr^).DataSource,sizeof(StringLL));
  1243.       end;
  1244.       freemem(FNP^.DataPtr,sizeof(ListCfg));
  1245.       FNP^.DataPtr := nil;
  1246.    end;
  1247. end; { DisposeListMemory }
  1248. {$IFDEF FOFF}
  1249.    {$F-}
  1250.    {$UNDEF FOFF}
  1251. {$ENDIF}
  1252.  
  1253. procedure ListAddItem(FieldID:integer; Str:string);
  1254. {}
  1255. var
  1256.    FNP: FieldNodePtr;
  1257.    SLP: StringLLPtr;
  1258. begin
  1259.    FNP := FieldPtr(FieldID);
  1260.    if (FNP <> nil) then
  1261.       with FNP^.FieldInfo^ do
  1262.       begin
  1263.          if not ((OMisc = ListFld) or (OMisc = ScrollFld)) then
  1264.             IOSetError(1007);
  1265.          if DataPtr = nil then
  1266.          begin
  1267.             if GoldMaxAvail < sizeof(SLP^)+sizeof(ListCfg) then
  1268.                IOSetError(1008);
  1269.             getmem(DataPtr,sizeof(ListCfg));
  1270.             initlistcfg(ListCfg(DataPtr^));
  1271.             ListCfg(DataPtr^).X1 := X1;
  1272.             ListCfg(DataPtr^).Y1 := Y1;
  1273.             ListCfg(DataPtr^).X2 := X2;
  1274.             ListCfg(DataPtr^).Y2 := Y2;
  1275.             with ListCfg(DataPtr^) do
  1276.             begin
  1277.                getmem(DataSource,sizeof(StringLL));
  1278.                SLP := DataSource;
  1279.                StrLLInit(SLP^);
  1280.                GetStr := SLGetStr;
  1281.                InWindow := (ActiveForm^.WinNum <> 0);
  1282.                ActiveNode := 1;
  1283.                TopNode := 1;
  1284.                Col[ListHi1] := IOVars.Form[IOVars.CurrentForm]^.Col[IOListHi];
  1285.                Col[ListHi2] := IOVars.Form[IOVars.CurrentForm]^.Col[IOListHiHot];
  1286.                Col[ListHiInactive] := IOVars.Form[IOVars.CurrentForm]^.Col[IOListHiInactive];
  1287.                Col[ListNorm1] := IOVars.Form[IOVars.CurrentForm]^.Col[IOListNorm];
  1288.                Col[ListNorm2] := IOVars.Form[IOVars.CurrentForm]^.Col[IOListNormHot];
  1289.                Col[ListOff] := IOVars.Form[IOVars.CurrentForm]^.Col[IOListOff];
  1290.                Col[ListScrollBarHi] := IOVars.Form[IOVars.CurrentForm]^.Col[IOListScroll];
  1291.                Col[ListScrollBarNorm] := IOVars.Form[IOVars.CurrentForm]^.Col[IOListScroll];
  1292.             end;
  1293.          end else
  1294.             SLP := ListCfg(DataPtr^).DataSource;
  1295.          if StrLLAdd(SLP^,Str) <> 0 then
  1296.             IOSetError(1008);
  1297.          inc(ListCfg(FNP^.FieldInfo^.DataPtr^).TotalNodes)
  1298.       end;
  1299. end; { ListAddItem }
  1300.  
  1301. procedure ListKwikAddItem(FieldID:integer; Str:string);
  1302. {Allows multiple items to be added in a single string with each
  1303.  item being separated using the StrVars.LineBreak character}
  1304. var P : byte;
  1305. begin
  1306.    P := 1;
  1307.    while P <> 0 do
  1308.    begin
  1309.       P := pos(StrVars.LineBreak,Str);
  1310.       if P = 0 then
  1311.          ListAddItem(FieldID,Str)
  1312.       else
  1313.       begin
  1314.          ListAddItem(FieldID,copy(Str,1,pred(P)));
  1315.          delete(Str,1,P);
  1316.       end;
  1317.    end;
  1318. end; { ListKwikAddItem }
  1319.  
  1320. procedure ListRebuild(FieldID:integer; Str:string);
  1321. {Erases the existing fields and adds first new item}
  1322. var FNP: FieldNodePtr;
  1323. begin
  1324.    FNP := FieldPtr(FieldID);
  1325.    if (FNP <> nil) then
  1326.    begin
  1327.       DisposeListMemory(FNP^.FieldInfo);
  1328.       ListKwikAddItem(FieldID,Str);
  1329.    end;
  1330. end; {ListRebuild}
  1331.  
  1332. procedure ListUpdateStrLL(FieldID:integer; var SL:StringLL);
  1333. {}
  1334. var FNP: FieldNodePtr;
  1335. begin
  1336.    FNP := FieldPtr(FieldID);
  1337.    if (FNP <> nil) then
  1338.       with ListCfg(FNP^.FieldInfo^.DataPtr^) do
  1339.       begin
  1340.          TotalNodes := SL.TotalNodes;
  1341.          ActiveNode := SL.ActiveNode;
  1342.          TopNode := SL.TopNode;
  1343.       end;
  1344.       with FNP^.FieldInfo^ do
  1345.          integer(SourcePtr^) := ListCfg(DataPtr^).ActiveNode;
  1346. end; { ListUpdateStrLL }
  1347.  
  1348. procedure ListAssignStrLL(FieldID:integer; var SL:StringLL);
  1349. {}
  1350. var FNP: FieldNodePtr;
  1351. begin
  1352.    FNP := FieldPtr(FieldID);
  1353.    if (FNP <> nil) then
  1354.       with FNP^.FieldInfo^ do
  1355.       begin
  1356.          if OMisc <> ListFld then
  1357.             IOSetError(1007);
  1358.          if DataPtr = nil then {no list already assigned}
  1359.             ListAddItem(FieldID,'Dummy');
  1360.          if ListCfg(DataPtr^).DataSource <> nil then
  1361.             StrLLDestroy(StringLLPtr(ListCfg(DataPtr^).DataSource)^);
  1362.          freemem(ListCfg(DataPtr^).DataSource,sizeof(StringLL));
  1363.          with ListCfg(DataPtr^) do
  1364.          begin
  1365.              DataSource := @SL;
  1366.              TotalNodes := SL.TotalNodes;
  1367.              ActiveNode := SL.ActiveNode;
  1368.              TopNode := SL.TopNode;
  1369.              {set flag so list is not disposed by DisposeFields}
  1370.              IODispose := false;
  1371.          end;
  1372.      end;
  1373. end; { ListAssignStrLL }
  1374.  
  1375.                      {**********************}
  1376.                      {**  List Functions  **}
  1377.                      {**********************}
  1378. function ListGetString(FieldID:integer; EntryNo:integer): string;
  1379. {Returns the highlighted string -- an EntryNo of zero returns the active node}
  1380. var FNP: FieldNodePtr;
  1381. begin
  1382.    FNP := FieldPtr(FieldID);
  1383.    if (FNP <> nil) then
  1384.    begin
  1385.       with ListCfg(FNP^.FieldInfo^.DataPtr^) do
  1386.       begin
  1387.          if EntryNo = 0 then
  1388.             EntryNo := ActiveNode;
  1389.          ListGetString := GetStr(DataSource,EntryNo,0,0);
  1390.       end;
  1391.    end
  1392.    else
  1393.       ListGetString := '';
  1394. end; { ListGetString }
  1395.  
  1396. function ListGetActivePick(FieldID:integer): integer;
  1397. {}
  1398. var FNP: FieldNodePtr;
  1399. begin
  1400.    FNP := FieldPtr(FieldID);
  1401.    if (FNP <> nil) then
  1402.       ListGetActivePick := ListCfg(FNP^.FieldInfo^.DataPtr^).ActiveNode
  1403.    else
  1404.       ListGetActivePick := 0;
  1405. end; { ListGetActivePick }
  1406.  
  1407. {$IFOPT F-}
  1408.    {$DEFINE FOFF}
  1409.    {$F+}
  1410. {$ENDIF}
  1411.  
  1412. procedure ListDisplay(FSP:FieldSettingsPtr;Status:gStatus);
  1413. {}
  1414. begin
  1415.    GListRefresh(ListCfg(FSP^.DataPtr^),Status);
  1416. end; { ListDisplay }
  1417.  
  1418. function ListKeyHandler(InKey:word;X,Y:byte):gAction;
  1419. {}
  1420. begin
  1421.    ListKeyHandler := none;
  1422.    with ActiveForm^.ActiveFieldPtr^.FieldInfo^ do
  1423.    begin
  1424.       GListProcessKey(ListCfg(DataPtr^),Inkey,X,Y,false);
  1425.       integer(SourcePtr^) := ListCfg(DataPtr^).ActiveNode;
  1426.    end;
  1427. end; { ListKeyHandler }
  1428.  
  1429. procedure ListRefreshField(FNP:FieldSettingsPtr);
  1430. {}
  1431. begin
  1432.    with FNP^ do
  1433.       if DataPtr <> nil then
  1434.       begin
  1435.          ListCfg(DataPtr^).ActiveNode := integer(SourcePtr^);
  1436.          StringLLPtr(ListCfg(DataPtr^).DataSource)^.ActiveNode := integer(SourcePtr^);
  1437.       end;
  1438. end; { ListRefreshField }
  1439.  
  1440. {$IFDEF FOFF}
  1441.    {$F-}
  1442.    {$UNDEF FOFF}
  1443. {$ENDIF}
  1444.  
  1445. function ListLastKey(FieldID:integer):word;
  1446. {}
  1447. var FNP: FieldNodePtr;
  1448. begin
  1449.    ListLastKey := 0;
  1450.    FNP := FieldPtr(FieldID);
  1451.    if (FNP <> nil) then
  1452.       with FNP^.FieldInfo^ do
  1453.          if DataPtr <> nil then
  1454.             ListLastKey := ListCfg(DataPtr^).LastKey;
  1455. end; { ListLastKey }
  1456.  
  1457. procedure ListField(FieldID:integer; width,depth:byte; var SelectedItem:integer);
  1458. {}
  1459. var FNP: FieldNodePtr;
  1460. begin
  1461.    FNP := FieldPtr(FieldID);
  1462.    if (FNP <> nil) then
  1463.       with FNP^.FieldInfo^ do
  1464.       begin
  1465.          SetFieldDefaults(FNP^.FieldInfo);
  1466.          X2 := X1 + pred(width);
  1467.          Y2 := Y1 + pred(depth);
  1468.          ProcesskeyHook := ListKeyHandler;
  1469.          SuspendHook := SuspendOK;
  1470.          DisplayHook := ListDisplay;
  1471.          DisposeHook := DisposeListMemory;
  1472.          RefreshFieldHook := ListRefreshField;    {change this}
  1473.          FieldStr    := '';
  1474.          FieldFmt    := '';
  1475.          FieldLen    := 0;
  1476.          FieldRules  := 0;
  1477.          OMisc       := ListFld;
  1478.          UsesCursors := true;
  1479.          SourcePtr := @SelectedItem;
  1480.       end;
  1481. end; { ListField }
  1482.  
  1483.                           {*********************}
  1484.                           {**  WrapListField  **}
  1485.                           {*********************}
  1486.  
  1487. {$IFOPT F-}
  1488.    {$DEFINE FOFF}
  1489.    {$F+}
  1490. {$ENDIF}
  1491.  
  1492. procedure WrapListDisplay(FSP:FieldSettingsPtr;Status:gStatus);
  1493. {}
  1494. begin
  1495.    WrapListRefresh(ListCfg(FSP^.DataPtr^),Status);
  1496. end; { WrapListDisplay }
  1497.  
  1498. function WrapListKeyHandler(InKey:word;X,Y:byte):gAction;
  1499. {}
  1500. begin
  1501.    WrapListKeyHandler := none;
  1502.    with ActiveForm^.ActiveFieldPtr^.FieldInfo^ do
  1503.       WrapListProcessKey(ListCfg(DataPtr^),Inkey,X,Y,false);
  1504. end; { WrapListKeyHandler }
  1505.  
  1506. {$IFDEF FOFF}
  1507.    {$F-}
  1508.    {$UNDEF FOFF}
  1509. {$ENDIF}
  1510.  
  1511. procedure WrapListField(FieldID:integer; Colwidth,ColCount,RowCount:byte;var ListDetails: ListCfg);
  1512. {}
  1513. var FNP: FieldNodePtr;
  1514. begin
  1515.    FNP := FieldPtr(FieldID);
  1516.    if (FNP <> nil) then
  1517.       with FNP^.FieldInfo^ do
  1518.       begin
  1519.          SetFieldDefaults(FNP^.FieldInfo);
  1520.          X2 := X1 + ColWidth*ColCount;  {last column is for scroill bar}
  1521.          Y2 := Y1 + pred(RowCount);
  1522.          Listdetails.X1 := X1;
  1523.          Listdetails.Y1 := Y1;
  1524.          Listdetails.X2 := X2;
  1525.          Listdetails.Y2 := Y2;
  1526.          Listdetails.ColWidth := ColWidth;
  1527.          RecalcListDimensions(Listdetails);
  1528.          ProcesskeyHook := WrapListKeyHandler;
  1529.          SuspendHook := SuspendOK;
  1530.          DisplayHook := WrapListDisplay;
  1531.          DisposeHook := BasicDisposeHook;
  1532.          FieldStr    := '';
  1533.          FieldFmt    := '';
  1534.          FieldLen    := 0;
  1535.          FieldRules  := 0;
  1536.          OMisc       := ListFld;
  1537.          UsesCursors := true;
  1538.          DataPtr := @Listdetails;
  1539.       end;
  1540. end; { WrapListField }
  1541.  
  1542.                           {*********************}
  1543.                           {**  GridListField  **}
  1544.                           {*********************}
  1545. {$IFOPT F-}
  1546.    {$DEFINE FOFF}
  1547.    {$F+}
  1548. {$ENDIF}
  1549.  
  1550. procedure GridListDisplay(FSP:FieldSettingsPtr;Status:gStatus);
  1551. {}
  1552. begin
  1553.    GridRefresh(ListCfg(FSP^.DataPtr^),Status);
  1554. end; { GridListDisplay }
  1555.  
  1556. function GridListKeyHandler(InKey:word;X,Y:byte):gAction;
  1557. {}
  1558. begin
  1559.    GridListKeyHandler := none;
  1560.    with ActiveForm^.ActiveFieldPtr^.FieldInfo^ do
  1561.       GridProcessKey(ListCfg(DataPtr^),Inkey,X,Y,false);
  1562. end; { GridListKeyHandler }
  1563.  
  1564. {$IFDEF FOFF}
  1565.    {$F-}
  1566.    {$UNDEF FOFF}
  1567. {$ENDIF}
  1568.  
  1569. procedure GridListField(FieldID:integer; width,depth:byte;var ListDetails: ListCfg);
  1570. {}
  1571. var FNP: FieldNodePtr;
  1572. begin
  1573.    FNP := FieldPtr(FieldID);
  1574.    if (FNP <> nil) then
  1575.       with FNP^.FieldInfo^ do
  1576.       begin
  1577.          SetFieldDefaults(FNP^.FieldInfo);
  1578.          X2 := pred(X1) + Width;
  1579.          Y2 := pred(Y1) + Depth;
  1580.          Listdetails.X1 := X1;
  1581.          Listdetails.Y1 := Y1;
  1582.          Listdetails.X2 := X2;
  1583.          Listdetails.Y2 := Y2;
  1584.          with Listdetails do
  1585.          begin
  1586.             if RowLock > 0 then
  1587.                TopNode := succ(RowLock);
  1588.             if ColumnLock > 0 then
  1589.                StartingCol := succ(ColumnLock);
  1590.          end;
  1591.          ProcesskeyHook := GridListKeyHandler;
  1592.          SuspendHook := SuspendOK;
  1593.          DisplayHook := GridListDisplay;
  1594.          DisposeHook := BasicDisposeHook;
  1595.          FieldStr    := '';
  1596.          FieldFmt    := '';
  1597.          FieldLen    := 0;
  1598.          FieldRules  := 0;
  1599.          OMisc       := ListFld;
  1600.          UsesCursors := true;
  1601.          DataPtr := @Listdetails;
  1602.       end;
  1603. end; { GridListField }
  1604.  
  1605.                            {********************}
  1606.                            {**  Scroll Field  **}
  1607.                            {********************}
  1608.  
  1609. procedure ScrollForceCase(FieldID:integer; FCase: gCase);
  1610. {}
  1611. var FNP: FieldNodePtr;
  1612. begin
  1613.    FNP := FieldPtr(FieldID);
  1614.    if (FNP <> nil) then
  1615.       with FNP^.FieldInfo^ do
  1616.       begin
  1617.          if OMisc <> ScrollFld then
  1618.             IOSetError(1010);
  1619.          ScrollInfoPtr(DataPtrS)^.Forcecase := FCase;
  1620.      end;
  1621. end; { ScrollForceCase }
  1622.  
  1623. procedure ScrollRedisplay(FSP:FieldSettingsPtr;Status:gStatus);
  1624. {}
  1625. var TempStr:strscreen;
  1626.     P,A: byte;
  1627.  
  1628.    procedure WriteScrollIcons;
  1629.    {}
  1630.    begin
  1631.       with FSP^ do
  1632.       with IOVars.Form[IOVars.CurrentForm]^ do
  1633.       with ScrollInfoPtr(DataPtrS)^ do
  1634.       begin
  1635.          if (Status in [Activate,HiStatus]) and (StartChar > 1) then
  1636.             WriteAT(X1,Y1,Col[IOIcons2],IO2Vars.ScrollLeft)
  1637.          else
  1638.             WriteAT(X1,Y1,A,' ');
  1639.          if (Status in [Activate,HiStatus])
  1640.          and (length(FieldStr) - StartChar >= FieldLen) then
  1641.             WriteAT(X2,Y1,Col[IOIcons2],IO2Vars.ScrollRight)
  1642.          else
  1643.             WriteAT(X2,Y1,A,' ');
  1644.       end;
  1645.    end; { WriteScrollIcons }
  1646.  
  1647. begin
  1648.    with FSP^ do
  1649.    with IOVars.Form[IOVars.CurrentForm]^ do
  1650.    with ScrollInfoPtr(DataPtrS)^ do
  1651.    begin
  1652.       FieldStr := AdjCase(ForceCase,FieldStr);
  1653.       TempStr := TruncFormat(FieldStr,StartChar,FieldLen,IOVars.Whitespace);
  1654.       if Status in [Activate,HiStatus] then
  1655.       begin
  1656.          GotoXY(CursorX,Y1);
  1657.          A := Col[IOEditHi];
  1658.          if FirstCharPress
  1659.          and (length(FieldStr) <> 0)
  1660.          and IsRule(FieldRules,EraseDefault) then
  1661.          begin
  1662.             WriteScrollIcons;
  1663.             P := pos(IOVars.Whitespace,TempStr);
  1664.             if (P = 0) then
  1665.                WriteAT(succ(X1),Y1,Col[IOEditErase],TempStr)
  1666.             else
  1667.             begin
  1668.                WriteAT(succ(X1),Y1,Col[IOEditErase],copy(TempStr,1,pred(P)));
  1669.                WriteAT(X1+P,Y1,Col[IOEditHi],copy(TempStr,P,80));
  1670.             end;
  1671.             exit;
  1672.          end;
  1673.       end
  1674.       else if Active = FldOn then
  1675.          A := Col[IOEditNorm]
  1676.       else
  1677.          A := Col[IOEditOff];
  1678.       WriteAT(succ(X1),Y1,A,TempStr);
  1679.       WriteScrollIcons;
  1680.    end;
  1681. end; { ScrollRedisplay }
  1682.  
  1683. {$IFOPT F-}
  1684.    {$DEFINE FOFF}
  1685.    {$F+}
  1686. {$ENDIF}
  1687.  
  1688. procedure ScrollRefresh(FSP:FieldSettingsPtr);
  1689. {}
  1690. begin
  1691.    if (FSP <> nil) then
  1692.       with FSP^ do
  1693.       begin
  1694.          FieldStr := VarToStr(FSP);
  1695.          StrLocX       := 1;
  1696.          CursorX       := succ(X1);
  1697.          with ScrollInfoPtr(DataPtrS)^ do
  1698.             StartChar := 1;
  1699.       end;
  1700. end; { ScrollRefresh }
  1701.  
  1702. function ScrollSuspend:boolean;
  1703. {}
  1704. begin
  1705.    with ActiveForm^.ActiveFieldPtr^.FieldInfo^ do
  1706.       if (FieldStr = '') and not IsRule(FieldRules,AllowNull) then
  1707.       begin
  1708.          CannotBeEmptyMessage;
  1709.          ScrollSuspend := false
  1710.       end
  1711.       else
  1712.          ScrollSuspend := true;
  1713. end; { ScrollSuspend }
  1714.  
  1715. procedure ScrollUpdate(FSP:FieldSettingsPtr);
  1716. {}
  1717. begin
  1718.    if (FSP <> nil) then
  1719.       with FSP^ do
  1720.            SPtr^ := FieldStr;
  1721. end; { ScrollUpdate }
  1722.  
  1723. procedure ScrollDisplay(FSP:FieldSettingsPtr;Status:gStatus);
  1724. {}
  1725. begin
  1726.    case Status of
  1727.       Activate,
  1728.       HiStatus:begin
  1729.           CursorOn;
  1730.           ScrollRedisplay(FSP,Status);
  1731.       end;
  1732.       OffStatus,
  1733.       NormStatus: ScrollRedisplay(FSP,Status);
  1734.    end; {case}
  1735. end; { ScrollDisplay }
  1736.  
  1737. function ScrollKeyHandler(InKey:word;X,Y:byte):gAction;
  1738. {Input handler used by the lateral scrolling string field}
  1739. var FSP: FieldSettingsPtr;
  1740.     K: char;
  1741.  
  1742.    procedure CursorLeft;
  1743.    {}
  1744.    begin
  1745.       with FSP^ do
  1746.       with ScrollInfoPtr(DataPtrS)^ do
  1747.       if StrLocX > 1 then
  1748.       begin
  1749.          if StrLocX = StartChar then
  1750.          begin
  1751.             dec(StartChar);
  1752.             dec(StrLocX);
  1753.             ScrollRedisplay(FSP,HiStatus)
  1754.          end else
  1755.          begin
  1756.             dec(CursorX);
  1757.             dec(StrLocX);
  1758.          end;
  1759.       end;
  1760.    end; { CursorLeft }
  1761.  
  1762.    procedure CursorRight;
  1763.    {}
  1764.    begin
  1765.       with FSP^ do
  1766.       with ScrollInfoPtr(DataPtrS)^ do
  1767.          if (StrLocX <= length(FieldStr)) and (StrLocX <= MaxLen) then
  1768.          begin
  1769.             if StrLocX - StartChar = FieldLen then
  1770.             begin
  1771.                inc(StartChar);
  1772.                inc(StrLocX);
  1773.                ScrollRedisplay(FSP,HiStatus);
  1774.             end else
  1775.             begin
  1776.                inc(CursorX);
  1777.                inc(StrLocX);
  1778.             end;
  1779.          end;
  1780.    end; { CursorRight }
  1781.  
  1782.    procedure CursorHome;
  1783.    {}
  1784.    begin
  1785.       with FSP^ do
  1786.       with ScrollInfoPtr(DataPtrS)^ do
  1787.       begin
  1788.          StrLocX := 1;
  1789.          CursorX := succ(X1);
  1790.          if StartChar <> 1 then
  1791.          begin
  1792.             StartChar := 1;
  1793.             ScrollRedisplay(FSP,HiStatus);
  1794.          end;
  1795.       end;
  1796.    end; { CursorHome }
  1797.  
  1798.    procedure CursorEnd;
  1799.    {}
  1800.    begin
  1801.       with FSP^ do
  1802.       with ScrollInfoPtr(DataPtrS)^ do
  1803.          if (StrLocX <= length(FieldStr)) then
  1804.          begin
  1805.             StrLocX := succ(length(FieldStr));
  1806.             if (StrLocX - StartChar) > FieldLen then
  1807.             begin
  1808.                StartChar := StrLocX - FieldLen;
  1809.                CursorX := X2;
  1810.                ScrollRedisplay(FSP,HiStatus);
  1811.             end else
  1812.                CursorX := succ(X1) + StrLocX - StartChar;
  1813.          end;
  1814.    end; { CursorEnd }
  1815.  
  1816.    procedure EraseField;
  1817.    {}
  1818.    begin
  1819.       with FSP^ do
  1820.       with ScrollInfoPtr(DataPtrS)^ do
  1821.       begin
  1822.          CursorX := succ(X1);
  1823.          StrLocX := 1;
  1824.          FieldStr := '';
  1825.          ScrollRedisplay(FSP,HiStatus);
  1826.       end;
  1827.    end; { EraseField }
  1828.  
  1829.    procedure DeleteChar;
  1830.    {}
  1831.    begin
  1832.       with FSP^ do
  1833.          if StrLocX <= length(FieldStr) then
  1834.          begin
  1835.             delete(FieldStr,StrLocX,1);
  1836.             ScrollRedisplay(FSP,HiStatus);
  1837.          end;
  1838.    end; { DeleteChar }
  1839.  
  1840.    procedure Backspaced;
  1841.    {}
  1842.    begin
  1843.       with FSP^ do
  1844.          if StrLocX > 1 then
  1845.          begin
  1846.             CursorLeft;
  1847.             DeleteChar;
  1848.             ScrollRedisplay(FSP,HiStatus);
  1849.          end;
  1850.    end; { Backspaced }
  1851.  
  1852.    procedure MouseDown;
  1853.    {}
  1854.    var L,C,R:boolean;
  1855.        LeftX,RightX,
  1856.        StartCursX,NewCursX,X,Y,P: byte;
  1857.        TempStr:string;
  1858.        WaitTime: integer;
  1859.  
  1860.        procedure MouseScrollLeft;
  1861.        {}
  1862.        var OldStartChar: byte;
  1863.        begin
  1864.           with FSP^ do
  1865.           with ScrollInfoPtr(DataPtrS)^ do
  1866.           begin
  1867.              CursorX := succ(X1);         {move cursor to left-most character}
  1868.              StrLocX := StartChar;
  1869.              repeat
  1870.                 MouseStatusWin(L,C,R,X,Y);
  1871.                 if (X = X1) and (Y = Y1) and L and (StartChar > 1) then
  1872.                 begin
  1873.                    OldStartChar := StartChar;
  1874.                    CursorLeft;
  1875.                    if (StartChar <> OldStartChar) then
  1876.                    begin
  1877.                       ScrollRedisplay(FSP,HiStatus);
  1878.                       if (ActiveForm^.WinNum <> 0) then
  1879.                          WinDrawTop;
  1880.                    end;
  1881.                 end;
  1882.                 DelayIt(L,(ActiveForm^.WinNum <> 0),WaitTime);
  1883.              until not L;
  1884.           end;
  1885.        end; { MouseScrollLeft }
  1886.  
  1887.        procedure MouseScrollRight;
  1888.        {}
  1889.        var OldStartChar: byte;
  1890.        begin
  1891.           with FSP^ do
  1892.           with ScrollInfoPtr(DataPtrS)^ do
  1893.           begin
  1894.              CursorX := pred(X2);               {move cursor to right-most character}
  1895.              StrLocX := CursorX - X1 - pred(StartChar);
  1896.              repeat
  1897.                 MouseStatusWin(L,C,R,X,Y);
  1898.                 if (X = X2) and (Y = Y1) and L and (length(FieldStr) - StartChar >= FieldLen) then
  1899.                 begin
  1900.                    OldStartChar := StartChar;
  1901.                    CursorRight;
  1902.                    if (StartChar <> OldStartChar) then
  1903.                    begin
  1904.                       ScrollRedisplay(FSP,HiStatus);
  1905.                       if (ActiveForm^.WinNum <> 0) then
  1906.                          WinDrawTop;
  1907.                    end;
  1908.                 end;
  1909.                 DelayIt(L,(ActiveForm^.WinNum <> 0),WaitTime);
  1910.              until not L;
  1911.           end;
  1912.        end; { MouseScrollRight }
  1913.  
  1914.        procedure MouseMoveCursor;
  1915.        {}
  1916.        begin
  1917.           with FSP^ do
  1918.           with ScrollInfoPtr(DataPtrS)^ do
  1919.           begin
  1920.              StartCursX := 0;
  1921.              TempStr := TruncFormat(FieldStr,StartChar,FieldLen,IOVars.Whitespace);
  1922.              LeftX := succ(X1);
  1923.              P := pos(IOVars.WhiteSpace,TempStr);
  1924.              if P = 0 then
  1925.                 RightX := pred(X2)
  1926.              else
  1927.                 RightX := X1 + P;
  1928.              repeat
  1929.                 MouseStatusWin(L,C,R,X,Y);
  1930.                 if L and (Y = Y1) and (X >= X1) and (X <= X2) then
  1931.                 begin
  1932.                    if (X >= LeftX) and (X <= RightX) then
  1933.                    begin
  1934.                       NewCursX := X;
  1935.                       if StartCursX = 0 then
  1936.                          StartCursX := NewCursX;
  1937.                       gotoxy(NewCursX,Y1);
  1938.                       if (FirstCharPress) then
  1939.                       begin  {clear the erase default setting}
  1940.                          FirstCharPress := false;
  1941.                          ScrollRedisplay(FSP,HiStatus);
  1942.                       end;
  1943.                       CursorX := NewCursX;
  1944.                    end;
  1945.                 end;
  1946.              until not L;
  1947.              StrLocX := pred(CursorX - X1 + StartChar);
  1948.           end;
  1949.        end; { MouseMoveCursor }
  1950.  
  1951.    begin
  1952.       with FSP^ do
  1953.       with ScrollInfoPtr(DataPtrS)^ do
  1954.       begin
  1955.          WaitTime := KeyVars.InitScrollDelay;
  1956.          MouseStatusWin(L,C,R,X,Y);
  1957.          if (X = X1) and (StartChar > 1) then
  1958.             MouseScrollleft
  1959.          else if (X = X2) and (length(FieldStr) - StartChar >= FieldLen) then
  1960.             MouseScrollRight
  1961.          else if (X >= X1) and (X <= X2) then
  1962.             MouseMoveCursor;
  1963.      end;
  1964.    end; { MouseDown }
  1965.  
  1966.    procedure InsertCharacter;
  1967.    {}
  1968.    begin
  1969.       with FSP^ do
  1970.       with ScrollInfoPtr(DataPtrS)^ do
  1971.          if (length(FieldStr) < MaxLen) then
  1972.          begin
  1973.             insert(K,FieldStr,StrLocX);
  1974.             CursorRight;
  1975.          end else
  1976.             FieldFullmessage;
  1977.    end; { InsertCharacter }
  1978.  
  1979.    procedure OvertypeCharacter;
  1980.    {}
  1981.    begin
  1982.       with FSP^ do
  1983.       begin
  1984.          delete(FieldStr,StrLocX,1);
  1985.          insert(K,FieldStr,StrLocX);
  1986.          CursorRight;
  1987.       end;
  1988.    end; { OvertypeCharacter }
  1989.  
  1990. begin
  1991.    FSP := ActiveForm^.ActiveFieldPtr^.FieldInfo;
  1992.    ScrollKeyHandler := none;
  1993.    K := WordToChar(InKey);
  1994.    with ActiveForm^ do
  1995.       if  (FSP^.AllowChar <> [#0])
  1996.       and (not (K in FSP^.AllowChar)) then
  1997.       begin
  1998.          if K <> NoChar then
  1999.             Beep;
  2000.          exit;
  2001.       end;
  2002.    with FSP^ do
  2003.    with ScrollInfoPtr(DataPtrS)^ do
  2004.    case Inkey of
  2005.       32..255 : begin
  2006.          case ForceCase of
  2007.             Lower: K := GetUpCase(K);
  2008.             Upper: K := GetLoCase(K);
  2009.          end;
  2010.          if ( (AllowChar = [#0])
  2011.               or
  2012.               ((AllowChar <> [#0]) and (K in AllowChar))
  2013.             )
  2014.          and ( (DisAllowChar = [#0])
  2015.                or ((DisAllowChar <> [#0]) and ((K in DisAllowChar)= false))
  2016.              )  then
  2017.          begin
  2018.             if FirstCharPress then
  2019.             begin
  2020.                if IsRule(FieldRules,EraseDefault) then
  2021.                    EraseField;
  2022.                FirstCharPress := false;
  2023.             end;
  2024.             if ActiveForm^.InsertMode then
  2025.                InsertCharacter
  2026.             else
  2027.                 OverTypeCharacter;
  2028.          end else
  2029.              Beep;
  2030.       end;
  2031.       339: DeleteChar;
  2032.       331: CursorLeft;
  2033.       333: CursorRight;
  2034.       338: with ActiveForm^ do
  2035.            begin
  2036.               InsertMode := not InsertMode;
  2037.               InsertProc(InsertMode);
  2038.            end;
  2039.       327: CursorHome;
  2040.       335: CursorEnd;
  2041.       8  : Backspaced;
  2042.       500: MouseDown;
  2043.       600..1000: ; {don't beep}
  2044.       else
  2045.          Beep;
  2046.   end; {case}
  2047. end; { ScrollKeyHandler }
  2048.  
  2049. procedure DisposeScrollMemory(FNP:FieldSettingsPtr);
  2050. {Disposes of heap memory allocated for scroll fields}
  2051. begin
  2052.    with FNP^ do
  2053.    if (DataPtrS <> nil) then
  2054.       freemem(DataPtrS,DataSize);
  2055. end; { DisposeScrollMemory }
  2056.  
  2057. {$IFDEF FOFF}
  2058.    {$F-}
  2059.    {$UNDEF FOFF}
  2060. {$ENDIF}
  2061.  
  2062. procedure ScrollField(FieldID:integer; var Strvar:string;FieldL,MaxL:byte);
  2063. {}
  2064. var FNP: FieldNodePtr;
  2065. begin
  2066.    FNP := FieldPtr(FieldID);
  2067.    if (FNP <> nil) then
  2068.       with FNP^.FieldInfo^ do
  2069.       begin
  2070.          SetFieldDefaults(FNP^.FieldInfo);
  2071.          SPtr          := @StrVar;
  2072.          FieldStr      := Sptr^;
  2073.          FieldLen      := FieldL - 2;
  2074.          FieldType     := IOString;
  2075.          StrLocX       := 1;
  2076.          CursorX       := succ(X1);
  2077.          X2 := X1 + pred(FieldL);
  2078.          ProcesskeyHook := ScrollKeyHandler;
  2079.          SuspendHook := ScrollSuspend;
  2080.          DisplayHook := ScrollDisplay;
  2081.          UpdateVarHook := ScrollUpdate;
  2082.          RefreshFieldHook := ScrollRefresh;
  2083.          DisposeHook := DisposeScrollMemory;
  2084.          OMisc       := ScrollFld;
  2085.          UsesCursors := false;
  2086.          dataSize := sizeof(ScrollInfo);
  2087.          getmem(DataPtrS,DataSize);
  2088.          with ScrollInfoPtr(DataPtrS)^ do
  2089.          begin
  2090.             Maxlen := MaxL;
  2091.             StartChar := 1;
  2092.             ForceCase := Leave;
  2093.          end;
  2094.       end;
  2095. end; { ScrollField }
  2096.  
  2097.                      {**********************************************}
  2098.                      {**  U N I T    I N I T I A L I Z A T I O N  **}
  2099.                      {**********************************************}
  2100. procedure IO2DefaultSettings;
  2101. {}
  2102. begin
  2103.    with IO2Vars do
  2104.    begin
  2105.       CheckOff := '[ ]';
  2106.       CheckOn := '[X]';
  2107.       RadioOff := '( )';
  2108.       RadioOn := '()';
  2109.       ScrollLeft := '';
  2110.       ScrollRight := '';
  2111.       ButtonLeft := ' ';
  2112.       ButtonRight := ' ';
  2113.    {$IFNDEF NOVGACHARS}
  2114.       FancyCheckOff := chr(208)+chr(209)+chr(183);
  2115.       FancyCheckOn := chr(208)+chr(210)+chr(183);
  2116.       FancyRadioOff := chr(211)+chr(212)+chr(184);
  2117.       FancyRadioOn := chr(211)+chr(213)+chr(184);
  2118.    {$ENDIF}
  2119.    end;
  2120. end; { IO2DefaultSettings }
  2121.  
  2122. procedure GoldIO2Init;
  2123. {}
  2124. begin
  2125.    IO2DefaultSettings;
  2126. end; {GoldIO2Init}
  2127.  
  2128. begin
  2129.    GoldIO2Init;
  2130. end.
  2131.